package gui.wizard;

import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Date;

import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.JToggleButton;
import javax.swing.SpinnerNumberModel;
import javax.swing.SwingConstants;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import no.ntnu.fp.swingutil.CalendarTools;

public class DateChooserComponent extends JPanel {

	private static final long serialVersionUID = 1L;
	public static String DAY = "Day";
	private CalendarTools ct;
	private int dayOfMonth, month, year;
	private Date currentMonthShowing, selectedMonth;
	private boolean isStartDate;
	private DaysPanel daysPanel;
	private JComboBox monthList;
	private JSpinner yearChooser;
	
	public DateChooserComponent() {
		ct = new CalendarTools();
		currentMonthShowing = new Date();
		selectedMonth = currentMonthShowing;
		isStartDate = false;
		dayOfMonth = ct.getDayOfMonth(currentMonthShowing);
		month = ct.getMonth(currentMonthShowing);
		year = ct.getYear(currentMonthShowing);
		daysPanel = new DaysPanel();
		
		monthList = new JComboBox(ct.getMonthNames());
		monthList.setSelectedIndex(ct.getMonth(currentMonthShowing));
		monthList.addActionListener(new MonthListAction());
		monthList.setPreferredSize(new Dimension(100, 30));
		if ( monthList.getItemCount() > 12 )
			monthList.removeItemAt(12);
		
		int currentYear = ct.getYear(new Date());
		yearChooser = new JSpinner(new SpinnerNumberModel(currentYear, currentYear-100, currentYear+100, 1));
		yearChooser.setEditor(new JSpinner.NumberEditor(yearChooser, "####"));
		yearChooser.setValue(currentYear);
		yearChooser.addChangeListener(new YearChooserAction());
		yearChooser.setPreferredSize(new Dimension(100, 30));
		
		JPanel monthAndYearPanel = new JPanel();
		monthAndYearPanel.add(monthList);
		monthAndYearPanel.add(yearChooser);
    	
    	setLayout(new BoxLayout(this,BoxLayout.Y_AXIS));
    	add(monthAndYearPanel);
    	add(daysPanel);
	}
	
	private DateChooserComponent getOwner() {
		return this;
	}
	
	public Date getSelectedDate() {
		return ct.getDate(year, month, dayOfMonth);
	}
	
	public void setSelectedDate(Date date) {
		currentMonthShowing = date;
		dayOfMonth = ct.getDayOfMonth(currentMonthShowing);
		month = ct.getMonth(currentMonthShowing);
		year = ct.getYear(currentMonthShowing);
		selectedMonth = date;
		drawNewMonth();
	}
	
	public boolean isSelected() {
		return daysPanel.isSelected();
	}
	
	private void drawNewMonth() {
		if ( ct.isSameDate(currentMonthShowing, selectedMonth, true, true, false, false, false) ) {
			isStartDate = true;
		} else {
			isStartDate = false;
		}
		remove(1);
		daysPanel = new DaysPanel();
		add(daysPanel, 1);
		validate();
	}
	
	private class MonthListAction implements ActionListener {
		public void actionPerformed(ActionEvent arg0) {
			int oldValue = month;
			month = (Integer)monthList.getSelectedIndex();
			currentMonthShowing = ct.setMonth(currentMonthShowing, month);
			drawNewMonth();
			firePropertyChange(DAY, oldValue, month);
		}
	}
	
	private class YearChooserAction implements ChangeListener {
		public void stateChanged(ChangeEvent arg0) {
			int oldValue = year;
			year = (Integer)yearChooser.getValue();
			currentMonthShowing = ct.setYear(currentMonthShowing, year);
			drawNewMonth();
			firePropertyChange(DAY, oldValue, month);
		}
	}

	private class DaysPanel extends JPanel implements ActionListener {
		
		private static final long serialVersionUID = 1L;
		private JLabel[] dayNames;
		private JToggleButton[] days;
		private ButtonGroup dayButtonGroup;
		
		public DaysPanel() {
			dayNames = new JLabel[7];
			days = new JToggleButton[49];
			dayButtonGroup = new ButtonGroup();
			drawDays(currentMonthShowing);
			drawDayNames();
			
			setLayout(new GridLayout(7, 7));
	    	setPreferredSize(new Dimension(300, 150));
	    	for (int i = 0; i < 49; i++) {
				if ( i < 7 ) {
					add(dayNames[i]);
				} else {
	    			add(days[i-7]);
				}
			}
		}
		
		public boolean isSelected() {
			for (int i = 0; i < days.length; i++) {
				if ( days[i].isShowing() && days[i].isSelected() ) {
					return true;
				}
			}
			return false;
		}
		
		private void drawDayNames() {
			String[] weekDays = ct.getShortDayNames();
			for (int i = 0; i < dayNames.length; i++) {
				dayNames[i] = new JLabel(weekDays[i]);
				dayNames[i].setHorizontalAlignment(SwingConstants.CENTER);
			}
		}
		
		private void drawDays(Date month) {
			for (int i = 0; i < days.length; i++) {
				days[i] = new JToggleButton("0");
				days[i].addActionListener(this);
				days[i].setMargin(new Insets(0, 0, 0, 0));
				dayButtonGroup.add(days[i]);
			}
			Date firstDayOfMonth = ct.getFirstDayOfMonth(month);
			String firstDayOfMonthName = ct.getDayName(firstDayOfMonth);
			String[] weekDays = ct.getDayNames();
			int weekDayStart = 0;
			for (int i = 0; i < weekDays.length; i++) {
				if ( firstDayOfMonthName.equals(weekDays[i]) ) {
					weekDayStart = i;
					break;
				}
				days[i].setVisible(false);
			}
			Date firstDayNextMonth = ct.setDayOfMonth(ct.getNextMonth(firstDayOfMonth), 1);
			Date date = firstDayOfMonth;
			int n = 0;
			int index = weekDayStart;
			while (date.before(firstDayNextMonth)) {
				index = weekDayStart + n;
				days[index].setText(Integer.toString(n + 1));
				days[index].setVisible(true);
				date = ct.getNextDay(date);
				n++;
			}
			for (int j = index + 1; j < days.length; j++) {
				days[j].setVisible(false);
			}
			Date now = new Date();
			if ( isStartDate ) {
				now = month;
			}
			int today = ct.getDayOfMonth(now);
			boolean disableDays = true;
			if ( ct.getMonth(month) != ct.getMonth(now) || ct.getYear(month) != ct.getYear(now) ) {
				if ( ct.isFirstDateBeforeSecondDate(month, now, true) ) {
					today = days.length - weekDayStart;
				} else if ( ct.isFirstDateBeforeSecondDate(now, month, true) ) {
					disableDays = false;
					days[0].setSelected(true);
				}
			}
			if ( disableDays ) {
				int j;
				for (j = weekDayStart; j < today + weekDayStart -1; j++) {
					days[j].setEnabled(false);
				}
				if ( today != days.length ) {
					days[j].setSelected(true);
				}
			}
		}

		public void actionPerformed(ActionEvent e) {
			int oldValue = dayOfMonth;
			dayOfMonth = Integer.parseInt(((JToggleButton)e.getSource()).getText());
			getOwner().firePropertyChange(DAY, oldValue, dayOfMonth);
		}

	}
	
}
